package com.wind.cloud.gateway.config;

import com.wind.cloud.common.constant.CommonConstant;
import com.wind.cloud.common.vo.ZuulRoute;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.zuul.filters.RefreshableRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * DB路由实现
 *
 * @author wind
 * @date 2018/10-19
 */
@Slf4j
public class DynamicRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator {
    private ZuulProperties properties;
    private BoundValueOperations<String, List<ZuulRoute>> boundListOperations;

    public DynamicRouteLocator(String servletPath, ZuulProperties properties,
                               RedisTemplate<String, List<ZuulRoute>> redisTemplate) {
        super(servletPath, properties);
        this.properties = properties;
        this.boundListOperations = redisTemplate.boundValueOps(CommonConstant.ROUTE_KEY);
    }

    @Override
    public Collection<String> getIgnoredPaths() {
        return Collections.emptyList();
    }

    /**
     * 重写路由配置
     * <p>
     * 1. properties 配置。
     * 2. eureka 默认配置。
     * 3. DB数据库配置。
     *
     * @return 路由表
     */
    @Override
    protected Map<String, ZuulProperties.ZuulRoute> locateRoutes() {
        return locateRoutesFromDb();
    }

    /**
     * 通过消息来更新？
     *
     * @return
     */
    private Map<String, ZuulProperties.ZuulRoute> locateRoutesFromDb() {
        Map<String, ZuulProperties.ZuulRoute> routes = new LinkedHashMap<>();


        List<ZuulRoute> results = boundListOperations.get();
        if (results == null) {
            return routes;
        }

        for (ZuulRoute result : results) {
            if (StringUtils.isEmpty(result.getPath())) {
                continue;
            }
            ZuulProperties.ZuulRoute zuulRoute = new ZuulProperties.ZuulRoute();
            zuulRoute.setId(result.getServiceId());
            zuulRoute.setPath(result.getPath());
            zuulRoute.setServiceId(result.getServiceId());
            zuulRoute.setRetryable(result.getRetryable());
            zuulRoute.setStripPrefix(result.getStripPrefix());
            if (!CollectionUtils.isEmpty(result.getSensitiveHeaders())) {
                zuulRoute.setSensitiveHeaders(result.getSensitiveHeaders());
            }
            String path = zuulRoute.getPath();
            if (!path.startsWith("/")) {
                path = "/" + path;
            }
            if (!StringUtils.isEmpty(this.properties.getPrefix())) {
                path = this.properties.getPrefix() + path;
                if (!path.startsWith("/")) {
                    path = "/" + path;
                }
            }
            routes.put(path, zuulRoute);
            log.debug("添加数据库自定义的路由配置,path:{}，serviceId:{}", path, zuulRoute.getServiceId());
        }
        return routes;
    }

    @Override
    public void refresh() {
        doRefresh();
    }

    @Override
    public int getOrder() {
        return 10;
    }
}
